/*
 * This file is part of ELCube.
 *
 * ELCube is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ELCube is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with ELCube.  If not, see <https://www.gnu.org/licenses/>.
 */
package cn.nkpro.elcube.co.spel;

import cn.nkpro.elcube.utils.MathUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 保留关键字
 */
@Component("SpELmath")
public class NkMathSpEL implements NkSpELInjection {

    private String pattern = "[^\\d-.]";

    public Number max(List<? extends Number> numbers){
        return numbers!=null?numbers.stream().max(Comparator.comparing(Number::doubleValue)).orElse(null):null;
    }
    public Number min(List<? extends Number> numbers){
        return numbers!=null?numbers.stream().min(Comparator.comparing(Number::doubleValue)).orElse(null):null;
    }
    public Number max(Number... numbers){
        return numbers!=null?Arrays.stream(numbers).max(Comparator.comparing(Number::doubleValue)).orElse(null):null;
    }
    public Number min(Number... numbers){
        return numbers!=null?Arrays.stream(numbers).min(Comparator.comparing(Number::doubleValue)).orElse(null):null;
    }

    public Double sumToDouble(List<? extends Number> numbers){
        return numbers!=null?numbers.stream().mapToDouble(Number::doubleValue).sum():0d;
    }

    public Long sumToLong(List<? extends Number> numbers){
        return numbers!=null?numbers.stream().mapToLong(Number::longValue).sum():0;
    }

    public Double currency(Object number){
        if(number instanceof Number){
            return MathUtils.currencyValue(((Number)number).doubleValue());
        }
        return null;
    }

    public int parseInt(String str){
        if(str==null)return 0;
        String s = str.replaceAll(pattern,"");
        int value = StringUtils.isNotBlank(s)?new BigDecimal(s).intValue(): 0;
        return str.contains("%")? (int) (value * 0.01) :value;
    }
    public long parseLong(String str){
        if(str==null)return 0;
        String s = str.replaceAll(pattern,"");
        long value =  StringUtils.isNotBlank(s)?new BigDecimal(s).longValue(): 0L;
        return str.contains("%")? (long) (value * 0.01) :value;
    }
    public double parseDouble(String str){
        if(str==null)return 0;
        String s = str.replaceAll(pattern,"");
        double value = StringUtils.isNotBlank(s)?new BigDecimal(s).doubleValue(): 0d;

        if(str.contains("%")){
             value *= 0.01;
        }
        if(str.contains("亿")){
            value *= 100000000;
        }
        if(str.contains("万")){
            value *= 10000;
        }
        if(str.contains("千")){
            value *= 1000;
        }
        return value;
    }

    public String parseCurrency(String str){
        str = StringUtils.upperCase(str);
        if(StringUtils.containsAny(str,"美元","USD","$")){
            return "USD";
        }
        if(StringUtils.containsAny(str,"港元","港币","HKD")){
            return "HKD";
        }
        if(StringUtils.containsAny(str,"欧元","EUR","€")){
            return "EUR";
        }
        if(StringUtils.containsAny(str,"英镑","GBP","£")){
            return "GBP";
        }
        if(StringUtils.containsAny(str,"日元","JPY")){
            return "JPY";
        }
        if(StringUtils.containsAny(str,"法郎","瑞士法郎","CHF")){
            return "CHF";
        }
        return "CNY";
    }
}
